package com.punai.evaluationSystem.incomeDataEvalute.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson2.JSON;
import com.github.pagehelper.PageHelper;
import com.punai.common.constant.HttpStatus;
import com.punai.common.core.page.PageDomain;
import com.punai.common.core.page.TableDataInfo;
import com.punai.common.core.page.TableSupport;
import com.punai.common.utils.PageUtils;
import com.punai.common.utils.StringUtil;
import com.punai.config.domain.ConfigInventoryChapter;
import com.punai.config.domain.ConfigInventoryLib;
import com.punai.config.mapper.ConfigInventoryChapterMapper;
import com.punai.config.mapper.ConfigInventoryLibMapper;
import com.punai.evaluationSystem.incomeDataEvalute.bo.Cascader;
import com.punai.evaluationSystem.incomeDataEvalute.bo.EvaluationDataPriceSrBo;
import com.punai.evaluationSystem.incomeDataEvalute.bo.IncomeDataEvaluteBo;
import com.punai.evaluationSystem.incomeDataEvalute.domain.EvaluationDataPriceSr;
import com.punai.evaluationSystem.incomeDataEvalute.domain.EvaluationResultsSr;
import com.punai.evaluationSystem.incomeDataEvalute.domain.EvaluationSrInfo;
import com.punai.evaluationSystem.incomeDataEvalute.mapper.EvaluationDataPriceSrMapper;
import com.punai.evaluationSystem.incomeDataEvalute.mapper.EvaluationResultsSrMapper;
import com.punai.evaluationSystem.incomeDataEvalute.mapper.EvaluationSrInfoMapper;
import com.punai.evaluationSystem.incomeDataEvalute.service.IncomeQdzhdjEvaluteService;
import com.punai.externalccb.domain.EcoCbfeeitem;
import com.punai.prodatalibrary.domain.LibProjectInfo;
import com.punai.prodatalibrary.mapper.LibProjectInfoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 收入数据评价
 */
@Service
@Transactional
public class IncomeQdzhdjEvaluteServiceImpl implements IncomeQdzhdjEvaluteService {
    @Autowired
    private EvaluationResultsSrMapper evaluationResultsSrMapper;
    @Autowired
    private EvaluationSrInfoMapper evaluationSrInfoMapper;
    @Autowired
    private LibProjectInfoMapper libProjectInfoMapper;
    @Autowired
    private EvaluationDataPriceSrMapper evaluationDataPriceSrMapper;
    @Autowired
    private ConfigInventoryChapterMapper configInventoryChapterMapper;
    @Autowired
    private ConfigInventoryLibMapper configInventoryLibMapper;

    @Override
    public List<EvaluationResultsSr> initResultsSrTable(IncomeDataEvaluteBo incomeDataEvaluteBo) {
        IncomeDataEvaluteBo convert = IncomeDataEvaluteBo.convert(incomeDataEvaluteBo);
        PageHelper.startPage(convert.getPageNum(),convert.getPageSize());
        List<EvaluationResultsSr> resultsList = evaluationResultsSrMapper.selectEvaluationResultsSr(new IncomeDataEvaluteBo() {{
            setInventoryStandard(convert.getInventoryStandard());
            setClassification(convert.getEvaluteType());
            setEvaluteType("02");
            setProjectDept(convert.getProjectDept());
            setAddress(convert.getAddress());
            setPriceType(convert.getPriceType());
            if (CollUtil.isNotEmpty(convert.getDateRange())){
                setTimeStart(convert.getDateRange().get(0));
                setTimeEnd(convert.getDateRange().get(1));
            }
        }});
        return resultsList;
    }

    @Override
    public int saveAssetLibrary(List<String> resultIds) {
        int i = evaluationResultsSrMapper.updateResultsSrByIdIn(resultIds,"1");
        return i;
    }

    @Override
    public List<Cascader> allProjectAddress() {
        List<Cascader> res = new ArrayList<Cascader>(){{
            add(new Cascader(){{
                setLabel("全部");
                setValue("全部");
            }});
        }};
        List<LibProjectInfo> infoList = libProjectInfoMapper.selectLibProjectInfoList(null);
        Map<String, List<LibProjectInfo>> groupByprovince = infoList.stream().filter(v -> v.getProvince() != null).collect(Collectors.groupingBy(LibProjectInfo::getProvince, Collectors.toList()));
        if (CollUtil.isNotEmpty(groupByprovince)){
            Set<String> provincekeySet = groupByprovince.keySet();
            for (String province : provincekeySet) {
                Cascader cascader = new Cascader();
                cascader.setLabel(province);
                cascader.setValue(province);
                setCityChildren(groupByprovince, cascader, province);
                res.add(cascader);
            }
        }
        return res;
    }

    //城市
    private static void setCityChildren(Map<String, List<LibProjectInfo>> groupByprovince,Cascader cascader,String province){
        List<Cascader> res = new ArrayList<>();
        //省份 -> 城市 || 城市 -> 地域
        Map<String, List<LibProjectInfo>> groupByCity = groupByprovince.get(province).stream().filter(v -> v.getCity() != null).collect(Collectors.groupingBy(LibProjectInfo::getCity, Collectors.toList()));
        if (CollUtil.isNotEmpty(groupByCity)){
            Set<String> keySet = groupByCity.keySet();
            for (String key : keySet) {
                Cascader cascaderNew = new Cascader();
                cascaderNew.setLabel(key);
                cascaderNew.setValue(key);
                setRegionChildren(groupByCity,cascaderNew,key);
                res.add(cascaderNew);
            }
            cascader.setChildren(res);
        }
    }

    //地域
    private static void setRegionChildren(Map<String, List<LibProjectInfo>> groupByCity,Cascader cascader,String city){
        List<Cascader> res = new ArrayList<>();
        //城市 -> 地域
        Map<String, List<LibProjectInfo>> groupByRegion = groupByCity.get(city).stream().filter(v -> v.getRegion() != null).collect(Collectors.groupingBy(LibProjectInfo::getRegion, Collectors.toList()));
        if (CollUtil.isNotEmpty(groupByRegion)){
            Set<String> keySet = groupByRegion.keySet();
            for (String key : keySet) {
                Cascader cascaderNew = new Cascader();
                cascaderNew.setLabel(key);
                cascaderNew.setValue(key);
                res.add(cascaderNew);
            }
            cascader.setChildren(res);
        }
    }

    @Override
    public List<IncomeDataEvaluteBo> initCleanDataTable(IncomeDataEvaluteBo incomeDataEvaluteBo) {
        return null;
    }

    @Override
    public TableDataInfo initCleanDataEvaluteTable(IncomeDataEvaluteBo evaluteBobo) {
        IncomeDataEvaluteBo incomeDataEvaluteBo = IncomeDataEvaluteBo.convert(evaluteBobo);
        List<EvaluationDataPriceSrBo> res = null;
        Long companyId = incomeDataEvaluteBo.getCompanyId();
        String categoryId = incomeDataEvaluteBo.getCategoryId();
        String type = incomeDataEvaluteBo.getType();
        List<String> idList = Arrays.asList(incomeDataEvaluteBo.getIdStr().split(",", -1));
        if(type.equals("fb_0")) { //分部分项清单
            res = new ArrayList<>();
            List<String> chapterIds = new ArrayList<>();
            chapterIds.add(categoryId);
            List<ConfigInventoryChapter> children = configInventoryChapterMapper.selectChildById(categoryId, companyId);
            if (CollUtil.isNotEmpty(children)) {
                for (ConfigInventoryChapter child : children) {
                    chapterIds.add(child.getId());
                }
            }
            List<ConfigInventoryLib> all = configInventoryLibMapper.selectConfigInventoryLibList(new ConfigInventoryLib() {{
                setCompanyId(incomeDataEvaluteBo.getCompanyId());
                setListNorm(incomeDataEvaluteBo.getInventoryStandard());
                setType(incomeDataEvaluteBo.getIncentoryType());
            }}, chapterIds);
            List<String> codes = all.stream().map(ConfigInventoryLib::getListCoding).collect(Collectors.toList());
            if(codes.size()!=0) incomeDataEvaluteBo.setCodes(codes);
            if (CollUtil.isNotEmpty(idList)){
                for (String id : idList) {
                    List<String> idAndAddress = Arrays.asList(id.split("=", -1));
                    if (CollUtil.isEmpty(idAndAddress)) continue;
                    incomeDataEvaluteBo.setId(idAndAddress.get(0));
                    incomeDataEvaluteBo.setAddress(idAndAddress.get(1));
                    incomeDataEvaluteBo.setPageSize(null);
                    List<IncomeDataEvaluteBo> boList = evaluationResultsSrMapper.selectCleanDataEvaluteList(incomeDataEvaluteBo);
                    if (CollUtil.isNotEmpty(boList)){
                        EvaluationDataPriceSrBo sr = new EvaluationDataPriceSrBo();
                        sr.setId(boList.get(0).getId());
                        sr.setCode(boList.get(0).getListCode());
                        sr.setName(boList.get(0).getListName());;
                        sr.setTzz(boList.get(0).getXmtz());
                        sr.setRegion(boList.get(0).getAddress());
                        sr.setJldw(boList.get(0).getJldw());
                        sr.setJgsl(boList.size());
                        sr.setGznr(boList.get(0).getGznr());
                        sr.setJsgz(boList.get(0).getJsgz());
                        sr.setYycs(boList.get(0).getYycs());
                        List<BigDecimal> priceList = boList.stream().filter(v -> v.getPrice() != null).map(IncomeDataEvaluteBo::getPrice).collect(Collectors.toList());
                        if (CollUtil.isNotEmpty(priceList)){
                            BigDecimal avgValue = priceList.stream().reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(boList.size()), 3, BigDecimal.ROUND_HALF_UP);
                            BigDecimal max = priceList.stream().max(Comparator.comparing(x -> x)).orElse(null).setScale(3,BigDecimal.ROUND_HALF_UP);
                            BigDecimal min = priceList.stream().min(Comparator.comparing(x -> x)).orElse(null).setScale(3,BigDecimal.ROUND_HALF_UP);
                            sr.setPriceRange(min +"-" +max);
                            BigDecimal modalNums = getModalNums(priceList);
                            BigDecimal jqAvg = getJqAvg2(id,null,evaluteBobo);
                            BigDecimal median = getMedian(priceList);
                            BigDecimal qdqxAvg = getQdqxAvg(priceList);
                            sr.setNumber(modalNums);//众数
                            sr.setSsavg(avgValue);//算数平均值
                            sr.setAvg(jqAvg);//加权平均值
                            sr.setMedian(median);//中位数
                            sr.setQdqxAvg(qdqxAvg);//去大去小平均值
                            //0：最大值 1：最小值 2：正常值
                            Map<BigDecimal,String> colorMap = new HashMap<BigDecimal,String>(){{
                                put(modalNums,"2");
                                put(avgValue,"2");
                                put(jqAvg,"2");
                                put(median,"2");
                                put(qdqxAvg,"2");
                            }};
                            List<BigDecimal> sortValue = colorMap.keySet().stream().filter(v->v!=null).sorted().collect(Collectors.toList());//进行排序
                            if (CollUtil.isNotEmpty(sortValue)){
                                BigDecimal minValue = sortValue.get(0);
                                BigDecimal maxValue = sortValue.get(sortValue.size() - 1);
                                colorMap.put(minValue,"0");
                                colorMap.put(maxValue,"1");
                            }
                            sr.setNumberColor(colorMap.get(modalNums));
                            sr.setSsavgColor(colorMap.get(avgValue));
                            sr.setAvgColor(colorMap.get(jqAvg));
                            sr.setMedianColor(colorMap.get(median));
                            sr.setQdqxAvgColor(colorMap.get(qdqxAvg));
                        }
                        res.add(sr);
                    }
                }
            }
        }else {
            res = new ArrayList<>();
            if (CollUtil.isNotEmpty(idList)){
                for (String id : idList) {
                    List<String> idAndAddress = Arrays.asList(id.split("=", -1));
                    if (CollUtil.isEmpty(idAndAddress)) continue;
                    incomeDataEvaluteBo.setId(idAndAddress.get(0));
                    incomeDataEvaluteBo.setAddress(idAndAddress.get(1));
                    incomeDataEvaluteBo.setPageSize(null);
                    List<IncomeDataEvaluteBo> boList = evaluationResultsSrMapper.selectCleanDataEvaluteList(incomeDataEvaluteBo);
                    if (CollUtil.isNotEmpty(boList)){
                        EvaluationDataPriceSrBo sr = new EvaluationDataPriceSrBo();
                        sr.setId(boList.get(0).getId());
                        sr.setCode(boList.get(0).getListCode());
                        sr.setName(boList.get(0).getListName());;
                        sr.setTzz(boList.get(0).getXmtz());
                        sr.setRegion(boList.get(0).getAddress());
                        sr.setJldw(boList.get(0).getJldw());
                        sr.setJgsl(boList.size());
                        sr.setGznr(boList.get(0).getGznr());
                        sr.setJsgz(boList.get(0).getJsgz());
                        sr.setYycs(boList.get(0).getYycs());
                        List<BigDecimal> priceList = boList.stream().filter(v -> v.getPrice() != null).map(IncomeDataEvaluteBo::getPrice).collect(Collectors.toList());
                        if (CollUtil.isNotEmpty(priceList)){
                            BigDecimal avgValue = priceList.stream().reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(boList.size()), 3, BigDecimal.ROUND_HALF_UP);
                            BigDecimal max = priceList.stream().max(Comparator.comparing(x -> x)).orElse(null).setScale(3,BigDecimal.ROUND_HALF_UP);
                            BigDecimal min = priceList.stream().min(Comparator.comparing(x -> x)).orElse(null).setScale(3,BigDecimal.ROUND_HALF_UP);
                            sr.setPriceRange(min +"-" +max);
                            BigDecimal modalNums = getModalNums(priceList);
                            BigDecimal jqAvg = getJqAvg2(id,null,evaluteBobo);
                            BigDecimal median = getMedian(priceList);
                            BigDecimal qdqxAvg = getQdqxAvg(priceList);
                            sr.setNumber(modalNums);//众数
                            sr.setSsavg(avgValue);//算数平均值
                            sr.setAvg(jqAvg);//加权平均值
                            sr.setMedian(median);//中位数
                            sr.setQdqxAvg(qdqxAvg);//去大去小平均值
                            //0：最大值 1：最小值 2：正常值
                            Map<BigDecimal,String> colorMap = new HashMap<BigDecimal,String>(){{
                                put(modalNums,"2");
                                put(avgValue,"2");
                                put(jqAvg,"2");
                                put(median,"2");
                                put(qdqxAvg,"2");
                            }};
                            List<BigDecimal> sortValue = colorMap.keySet().stream().filter(v->v!=null).sorted().collect(Collectors.toList());//进行排序
                            if (CollUtil.isNotEmpty(sortValue)){
                                BigDecimal minValue = sortValue.get(0);
                                BigDecimal maxValue = sortValue.get(sortValue.size() - 1);
                                colorMap.put(minValue,"0");
                                colorMap.put(maxValue,"1");
                            }
                            sr.setNumberColor(colorMap.get(modalNums));
                            sr.setSsavgColor(colorMap.get(avgValue));
                            sr.setAvgColor(colorMap.get(jqAvg));
                            sr.setMedianColor(colorMap.get(median));
                            sr.setQdqxAvgColor(colorMap.get(qdqxAvg));
                        }
                        res.add(sr);
                    }
                }
            }
        }
        PageDomain pageDomain = TableSupport.buildPageRequest();
        int pageSize = pageDomain.getPageSize();
        int start = (pageDomain.getPageNum()-1) * pageSize;
        int end = start + pageSize;
        if (end>res.size()) end = res.size();
        List<EvaluationDataPriceSrBo> list = res.subList(start, end);

        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setMsg("查询成功");
        rspData.setRows(list);
        rspData.setTotal(res.size());
        return rspData;
    }

    @Override
    public List<IncomeDataEvaluteBo> initTableDetailInfoData(IncomeDataEvaluteBo incomeDataEvaluteBo) {
        return null;
    }

    @Override
    public List<String> cleanDataInfoIdList(IncomeDataEvaluteBo incomeDataEvaluteBo) {
        return null;
    }

    @Override
    public EvaluationDataPriceSrBo recalculationQdzhdj(IncomeDataEvaluteBo evaluteBo) {
        IncomeDataEvaluteBo incomeDataEvaluteBo = IncomeDataEvaluteBo.convert(evaluteBo);
        EvaluationDataPriceSrBo sr = new EvaluationDataPriceSrBo();
        List<String> singleFeeId = Arrays.asList(incomeDataEvaluteBo.getSingleFeeId().split("=", -1));
        List<String> ids = Arrays.asList(incomeDataEvaluteBo.getIdStr().split(",", -1));
        if (CollUtil.isNotEmpty(singleFeeId)){
            String id = singleFeeId.get(0);
            String address = singleFeeId.get(1);
            sr.setId(id);
            sr.setRegion(address);
            incomeDataEvaluteBo.setId(id);
            incomeDataEvaluteBo.setAddress(address);
            incomeDataEvaluteBo.setOids(ids);
            List<IncomeDataEvaluteBo> boList = null;
            if (StringUtil.isNotNullOrEmpty(incomeDataEvaluteBo.getType()) && incomeDataEvaluteBo.getType().equals("view")){
                boList = evaluationSrInfoMapper.initTableDetailInfoData(incomeDataEvaluteBo);
            }else {
                boList = evaluationResultsSrMapper.selectCleanDataEvaluteList(incomeDataEvaluteBo);
            }
            if (CollUtil.isNotEmpty(boList)){
                sr.setCode(boList.get(0).getListCode());
                sr.setName(boList.get(0).getListName());;
                sr.setTzz(boList.get(0).getXmtz());
                sr.setJldw(boList.get(0).getJldw());
                sr.setJgsl(boList.size());
                sr.setGznr(boList.get(0).getGznr());
                sr.setJsgz(boList.get(0).getJsgz());
                sr.setYycs(boList.get(0).getYycs());
                List<BigDecimal> priceList = boList.stream().filter(v -> v.getPrice() != null).map(IncomeDataEvaluteBo::getPrice).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(priceList)){
                    BigDecimal avgValue = priceList.stream().reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(boList.size()), 3, BigDecimal.ROUND_HALF_UP);
                    BigDecimal max = priceList.stream().max(Comparator.comparing(x -> x)).orElse(null).setScale(3,BigDecimal.ROUND_HALF_UP);
                    BigDecimal min = priceList.stream().min(Comparator.comparing(x -> x)).orElse(null).setScale(3,BigDecimal.ROUND_HALF_UP);
                    sr.setPriceRange(min +"-" +max);
                    BigDecimal modalNums = getModalNums(priceList);
                    BigDecimal jqAvg = getJqAvg(boList,incomeDataEvaluteBo.getJqAvg());
                    BigDecimal median = getMedian(priceList);
                    BigDecimal qdqxAvg = getQdqxAvg(priceList);
                    sr.setNumber(modalNums);//众数
                    sr.setSsavg(avgValue);//算数平均值
                    sr.setAvg(jqAvg);//加权平均值
                    sr.setMedian(median);//中位数
                    sr.setQdqxAvg(qdqxAvg);//去大去小平均值
                    //0：最小值 1：最大值 2：正常值
                    Map<BigDecimal,String> colorMap = new HashMap<BigDecimal,String>(){{
                        put(modalNums,"2");
                        put(avgValue,"2");
                        put(jqAvg,"2");
                        put(median,"2");
                        put(qdqxAvg,"2");
                    }};
                    List<BigDecimal> sortValue = colorMap.keySet().stream().filter(v->v!=null).sorted().collect(Collectors.toList());//进行排序
                    if (CollUtil.isNotEmpty(sortValue)){
                        BigDecimal minValue = sortValue.get(0);
                        BigDecimal maxValue = sortValue.get(sortValue.size() - 1);
                        colorMap.put(minValue,"0");
                        colorMap.put(maxValue,"1");
                    }
                    sr.setNumberColor(colorMap.get(modalNums));
                    sr.setSsavgColor(colorMap.get(avgValue));
                    sr.setAvgColor(colorMap.get(jqAvg));
                    sr.setMedianColor(colorMap.get(median));
                    sr.setQdqxAvgColor(colorMap.get(qdqxAvg));
                }
            }
        }
        return sr;
    }

    @Override
    public int saveEvaluationPrice(IncomeDataEvaluteBo evaluteBo) {
        int insert;
        IncomeDataEvaluteBo incomeDataEvaluteBo = IncomeDataEvaluteBo.convert(evaluteBo);
        String titleName = incomeDataEvaluteBo.getName();
        List<EvaluationDataPriceSr> qdSaveData = incomeDataEvaluteBo.getQdSaveData();
        List<String> ids = incomeDataEvaluteBo.getIds();//明细id
        Map<BigDecimal, List<EvaluationDataPriceSr>> btjgsl = qdSaveData.stream().filter(v -> v.getUserPrice() != null).collect(Collectors.groupingBy(EvaluationDataPriceSr::getUserPrice, Collectors.toList()));
        //保存结果表
        EvaluationResultsSr resultsSr = new EvaluationResultsSr();
        resultsSr.setIsassets(0);//不存在资产库
        resultsSr.setEvaluateType("02");
        resultsSr.setClassification(incomeDataEvaluteBo.getType());
        resultsSr.setPjjgsj(titleName);
        resultsSr.setCount(qdSaveData.size());
        resultsSr.setBtjgsl(btjgsl.size());
        resultsSr.setPriceType(incomeDataEvaluteBo.getInventoryStandard());
        insert = evaluationResultsSrMapper.insert(resultsSr);
        //保存数据明细表
        if (CollUtil.isNotEmpty(qdSaveData)){
            for (EvaluationDataPriceSr qdSaveDatum : qdSaveData) {
                qdSaveDatum.setAvgType(incomeDataEvaluteBo.getJqAvg());
                qdSaveDatum.setClassification(incomeDataEvaluteBo.getType());
                qdSaveDatum.setOid(qdSaveDatum.getId());
                qdSaveDatum.setPid(resultsSr.getId());
                qdSaveDatum.setId(null);
                insert = evaluationDataPriceSrMapper.insert(qdSaveDatum);
                if (CollUtil.isNotEmpty(ids)){
                    List<IncomeDataEvaluteBo> boList = evaluationResultsSrMapper.selectCleanDataEvaluteList(new IncomeDataEvaluteBo(){{
                        setAddress(qdSaveDatum.getRegion());
                        setId(qdSaveDatum.getOid());
                        setOids(ids);
                    }});
                    List<EvaluationSrInfo> convertSrInfo = EvaluationSrInfo.convert(qdSaveDatum.getId(), boList);
                    if (CollUtil.isNotEmpty(convertSrInfo)){
                        for (EvaluationSrInfo info : convertSrInfo) {
                            insert = evaluationSrInfoMapper.insert(info);
                        }
                    }
                }
            }
        }
        return insert;
    }

    @Override
    public int updateEvaluationPrice(IncomeDataEvaluteBo incomeDataEvaluteBo) {
        int i;
        String resultId = incomeDataEvaluteBo.getId();
        String titleName = incomeDataEvaluteBo.getName();
        List<EvaluationDataPriceSr> qdSaveData = incomeDataEvaluteBo.getQdSaveData();
        List<String> ids = incomeDataEvaluteBo.getIds();//明细id
        Map<BigDecimal, List<EvaluationDataPriceSr>> btjgsl = qdSaveData.stream().filter(v -> v.getUserPrice() != null).collect(Collectors.groupingBy(EvaluationDataPriceSr::getUserPrice, Collectors.toList()));
        //修改结果表
        EvaluationResultsSr resultsSr = evaluationResultsSrMapper.selectEvaluationResultsSrById(resultId);
        resultsSr.setPjjgsj(titleName);
        resultsSr.setBtjgsl(btjgsl.size());
        resultsSr.setCount(qdSaveData.size());
        i = evaluationResultsSrMapper.updateById(resultsSr);
        //删除未选中的数据
        List<EvaluationDataPriceSr> dataPriceSrList = evaluationDataPriceSrMapper.selectEvaluationDataPriceSrList(new EvaluationDataPriceSr() {{
            setPid(resultId);
        }});
        List<String> dataPriceSrIds = qdSaveData.stream().map(EvaluationDataPriceSr::getId).collect(Collectors.toList());
        List<String> deleteDataIds = dataPriceSrList.stream().filter(v -> !dataPriceSrIds.contains(v.getId())).map(EvaluationDataPriceSr::getId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(deleteDataIds)){
            i = evaluationDataPriceSrMapper.deleteBatchIds(deleteDataIds);
        }
        //修改 数据明细
        for (EvaluationDataPriceSr saveDatum : qdSaveData) {
            EvaluationDataPriceSr dataPriceSr = evaluationDataPriceSrMapper.selectEvaluationDataPriceSrById(saveDatum.getId());
            dataPriceSr.setJgsl(saveDatum.getJgsl());
            dataPriceSr.setNumber(saveDatum.getNumber());
            dataPriceSr.setSsavg(saveDatum.getSsavg());
            dataPriceSr.setAvg(saveDatum.getAvg());
            dataPriceSr.setAvgType(incomeDataEvaluteBo.getJqAvg());
            dataPriceSr.setMedian(saveDatum.getMedian());
            dataPriceSr.setQdqxAvg(saveDatum.getQdqxAvg());
            dataPriceSr.setUserPrice(saveDatum.getUserPrice());
            dataPriceSr.setPriceRange(saveDatum.getPriceRange());
            dataPriceSr.setEvaluationDate(new Date());
            i = evaluationDataPriceSrMapper.updateById(dataPriceSr);
            if (CollUtil.isNotEmpty(ids)){
                List<EvaluationSrInfo> evaluationSrInfos = evaluationSrInfoMapper.selectEvaluationSrInfoList(new EvaluationSrInfo() {{
                    setPid(saveDatum.getId());
                }});
                List<String> infoIds = evaluationSrInfos.stream().filter(v->!ids.contains(v.getOid())).map(EvaluationSrInfo::getId).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(infoIds)){
                    i = evaluationSrInfoMapper.deleteBatchIds(infoIds);
                }
            }
        }
        return i;
    }

    @Override
    public List<EvaluationDataPriceSrBo> initEvaluteDataList(IncomeDataEvaluteBo incomeDataEvaluteBo) {
        List<EvaluationDataPriceSrBo> res = new ArrayList<>();
        Long companyId = incomeDataEvaluteBo.getCompanyId();
        String categoryId = incomeDataEvaluteBo.getCategoryId();
        String type = incomeDataEvaluteBo.getTabType();
        List<String> codes = new ArrayList<>();
        if(type.equals("fb_0")) { //分部分项清单
            res = new ArrayList<>();
            List<String> chapterIds = new ArrayList<>();
            chapterIds.add(categoryId);
            List<ConfigInventoryChapter> children = configInventoryChapterMapper.selectChildById(categoryId, companyId);
            if (CollUtil.isNotEmpty(children)) {
                for (ConfigInventoryChapter child : children) {
                    chapterIds.add(child.getId());
                }
            }
            List<ConfigInventoryLib> all = configInventoryLibMapper.selectConfigInventoryLibList(new ConfigInventoryLib() {{
                setCompanyId(incomeDataEvaluteBo.getCompanyId());
                setListNorm(incomeDataEvaluteBo.getInventoryStandard());
                setType(incomeDataEvaluteBo.getIncentoryType());
            }}, chapterIds);
            codes = all.stream().map(ConfigInventoryLib::getListCoding).collect(Collectors.toList());
        }
        PageUtils.startPage();
        List<EvaluationDataPriceSr> list = evaluationDataPriceSrMapper.selectEvaluationDataPriceSrList(new EvaluationDataPriceSr() {{
            setCode(incomeDataEvaluteBo.getListCode());
            setName(incomeDataEvaluteBo.getListName());
            setPid(incomeDataEvaluteBo.getId());
        }});
        for (EvaluationDataPriceSr dataPriceSr : list) {
            if (CollUtil.isNotEmpty(codes) && !codes.contains(dataPriceSr.getCode())) continue;
            EvaluationDataPriceSrBo bo = new EvaluationDataPriceSrBo();
            BeanUtil.copyProperties(dataPriceSr,bo);
            BigDecimal modalNums = bo.getNumber();
            BigDecimal avgValue = bo.getSsavg();
            BigDecimal jqAvg = null;
            if (incomeDataEvaluteBo.getJqAvg()!=null){
                StringBuilder idAndAddress = new StringBuilder().append(bo.getOid()).append("=").append(bo.getRegion());
                jqAvg = getJqAvg2(idAndAddress.toString(),"view",incomeDataEvaluteBo);
                bo.setAvg(jqAvg);
            }else {
                jqAvg = bo.getAvg();
            }
            BigDecimal median = bo.getMedian();
            BigDecimal qdqxAvg = bo.getQdqxAvg();
            BigDecimal finalJqAvg = jqAvg;
            Map<BigDecimal,String> colorMap = new HashMap<BigDecimal,String>(){{
                put(modalNums,"2");
                put(avgValue,"2");
                put(finalJqAvg,"2");
                put(median,"2");
                put(qdqxAvg,"2");
            }};
            List<BigDecimal> sortValue = colorMap.keySet().stream().filter(v->v!=null).sorted().collect(Collectors.toList());//进行排序
            if (CollUtil.isNotEmpty(sortValue)){
                BigDecimal minValue = sortValue.get(0);
                BigDecimal maxValue = sortValue.get(sortValue.size() - 1);
                colorMap.put(minValue,"0");
                colorMap.put(maxValue,"1");
            }
            bo.setNumberColor(colorMap.get(modalNums));
            bo.setSsavgColor(colorMap.get(avgValue));
            bo.setAvgColor(colorMap.get(finalJqAvg));
            bo.setMedianColor(colorMap.get(median));
            bo.setQdqxAvgColor(colorMap.get(qdqxAvg));
            res.add(bo);
        }
        return res;
    }

    @Override
    public List<String> evaluteDataInfoIdList(IncomeDataEvaluteBo incomeDataEvaluteBo) {
        List<IncomeDataEvaluteBo> boList = evaluationSrInfoMapper.initTableDetailInfoData(new IncomeDataEvaluteBo() {{
            setPid(incomeDataEvaluteBo.getId());
        }});
        return boList.stream().map(IncomeDataEvaluteBo::getId).collect(Collectors.toList());
    }

    /**
     * 众数
     * @param list
     * @return
     */
    public static BigDecimal getModalNums(List<BigDecimal> list) {
        Map<BigDecimal, Integer> map = new HashMap<>();
        if (list == null || list.size() == 0) {
            return null;
        }
        for (BigDecimal num : list) {
            Integer count = map.get(num);
            map.put(num,(count == null) ? 1 : count + 1);
        }
        Object[] objects = map.values().toArray();
        Arrays.sort(objects);
        Object object = objects[map.size() - 1];//值最大
        BigDecimal number = null;
        Set<BigDecimal> keys = map.keySet();
        for (BigDecimal key : keys) {
            Integer integer = map.get(key);
            if (integer.equals(object)){
                number = key;
            }
        }
        return number.setScale(3,BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 加权平均值
     * @param boList
     * @param option 下拉框选项
     * @return
     */
    public BigDecimal getJqAvg(List<IncomeDataEvaluteBo> boList,String option) {
        BigDecimal avg = null;
        Map<BigDecimal, List<IncomeDataEvaluteBo>> listMap = boList.stream().filter(v -> v.getPrice() != null).collect(Collectors.groupingBy(IncomeDataEvaluteBo::getPrice, Collectors.toList()));
        if (CollUtil.isNotEmpty(listMap)){
            Integer jgcsQS = 0; //'价格次数'权数之和
            double gclQS = 0;  //'工程量'权数之和
            double jgcsTotal = 0; // 兼 '成本合价'权数之和
            double gclTotal = 0;
            double cbhjTotal = 0;
            Set<BigDecimal> key = listMap.keySet();
            for (BigDecimal price : key) {
                BigDecimal unitPrice = price;//价格
                int jgcs = listMap.get(price).size();//价格次数
                if(StringUtil.isNotNullOrEmpty(option) && option.equals("2")){
                    List<String> dataJsonList = listMap.get(price).stream().filter(v -> v.getLinkDataJson() != null).map(IncomeDataEvaluteBo::getLinkDataJson).collect(Collectors.toList());
                    BigDecimal gcl = getGcl(dataJsonList);//该工程量指：同一价格的不同工程量之和
                    if (gcl != null) gclQS += gcl.doubleValue();
                    if (gcl != null && unitPrice != null) gclTotal += unitPrice.multiply(gcl).doubleValue();
                }
                jgcsQS += jgcs;
                jgcsTotal += unitPrice.multiply(new BigDecimal(jgcs)).doubleValue(); // 不同价格 x 次数
                cbhjTotal += unitPrice.multiply(unitPrice.multiply(new BigDecimal(jgcs))).doubleValue(); // 不同价格 x 成本合价
            }
            if (StringUtil.isNullOrEmpty(option) || option.equals("0") || option.equals("1")){
                //以出现次数为权数
                if (jgcsTotal == 0 || jgcsQS == 0) return new BigDecimal("0.000");
                avg = new BigDecimal(jgcsTotal).divide(new BigDecimal(jgcsQS),3,BigDecimal.ROUND_HALF_UP);
            }else if (option.equals("2")){
                //以工程量为权数
                if (gclTotal == 0 || gclQS == 0) return new BigDecimal("0.000");
                avg = new BigDecimal(gclTotal).divide(new BigDecimal(gclQS),3,BigDecimal.ROUND_HALF_UP);
            }else if (option.equals("3")){
                //以合价为权数
                if (cbhjTotal == 0 || jgcsTotal == 0) return new BigDecimal("0.000");
                avg = new BigDecimal(cbhjTotal).divide(new BigDecimal(jgcsTotal),3,BigDecimal.ROUND_HALF_UP);
            }
        }
        return avg;
    }

    /**
     * 加权平均值
     * @param id id+address
     * @param viewOrEdit
     * @param bo
     * @return
     */
    public BigDecimal getJqAvg2(String id,String viewOrEdit,IncomeDataEvaluteBo bo) {
        //获取该条数据的id 根据id获取对应price和count（price）
        if (StringUtil.isNullOrEmpty(id)) return null;
        String option = bo.getJqAvg();//下拉框选项
        BigDecimal avg = null;
        List<String> idAndAddress = Arrays.asList(id.split("=", -1));
        if (CollUtil.isEmpty(idAndAddress)) return null;
        String sreachId = idAndAddress.get(0);
        if(viewOrEdit != null && viewOrEdit.equals("view")){
            EvaluationDataPriceSr dataPriceSr = evaluationDataPriceSrMapper.selectEvaluationDataPriceSrById(idAndAddress.get(0));
            if (dataPriceSr != null) sreachId = dataPriceSr.getOid();
        }
        String finalSreachId = sreachId;
        List<IncomeDataEvaluteBo> boList = evaluationResultsSrMapper.selectCleanDataEvaluteList(new IncomeDataEvaluteBo(){{
            setId(finalSreachId);
            setAddress(idAndAddress.get(1));
            setPriceType(bo.getPriceType());
            setProjectDept(bo.getProjectDept());
            setOids(bo.getList());
        }});
        Map<BigDecimal, List<IncomeDataEvaluteBo>> listMap = boList.stream().filter(v -> v.getPrice() != null).collect(Collectors.groupingBy(IncomeDataEvaluteBo::getPrice, Collectors.toList()));
        if (CollUtil.isNotEmpty(listMap)){
            Integer jgcsQS = 0; //'价格次数'权数之和
            double gclQS = 0;  //'工程量'权数之和
            double jgcsTotal = 0; // 兼 '成本合价'权数之和
            double gclTotal = 0;
            double cbhjTotal = 0;
            Set<BigDecimal> key = listMap.keySet();
            for (BigDecimal price : key) {
                BigDecimal unitPrice = price;//价格
                int jgcs = listMap.get(price).size();//价格次数
                if(StringUtil.isNotNullOrEmpty(option) && option.equals("2")){
                    List<String> dataJsonList = listMap.get(price).stream().filter(v -> v.getLinkDataJson() != null).map(IncomeDataEvaluteBo::getLinkDataJson).collect(Collectors.toList());
                    BigDecimal gcl = getGcl(dataJsonList);//该工程量指：同一价格的不同工程量之和
                    if (gcl != null) gclQS += gcl.doubleValue();
                    if (gcl != null && unitPrice != null) gclTotal += unitPrice.multiply(gcl).doubleValue();
                }
                jgcsQS += jgcs;
                jgcsTotal += unitPrice.multiply(new BigDecimal(jgcs)).doubleValue(); // 不同价格 x 次数
                cbhjTotal += unitPrice.multiply(unitPrice.multiply(new BigDecimal(jgcs))).doubleValue(); // 不同价格 x 成本合价
            }
            if (StringUtil.isNullOrEmpty(option) || option.equals("0") || option.equals("1")){
                //以出现次数为权数
                if (jgcsTotal == 0 || jgcsQS == 0) return new BigDecimal("0.0000");
                avg = new BigDecimal(jgcsTotal).divide(new BigDecimal(jgcsQS),3,BigDecimal.ROUND_HALF_UP);
            }else if (option.equals("2")){
                //以工程量为权数
                if (gclTotal == 0 || gclQS == 0) return new BigDecimal("0.0000");
                avg = new BigDecimal(gclTotal).divide(new BigDecimal(gclQS),3,BigDecimal.ROUND_HALF_UP);
            }else if (option.equals("3")){
                //以合价为权数
                if (cbhjTotal == 0 || jgcsTotal == 0) return new BigDecimal("0.0000");
                avg = new BigDecimal(cbhjTotal).divide(new BigDecimal(jgcsTotal),3,BigDecimal.ROUND_HALF_UP);
            }
        }
        return avg;
    }

    /**
     * 工程量
     * @param linkDataJsonList
     * @return
     */
    public BigDecimal getGcl(List<String> linkDataJsonList) {
        BigDecimal gcl = null;
        if (CollUtil.isEmpty(linkDataJsonList)) return gcl;
        if (CollUtil.isNotEmpty(linkDataJsonList)){
            List<EcoCbfeeitem> cbFeeItemList = new ArrayList<>();
            for (String data : linkDataJsonList) {
                List<EcoCbfeeitem> cbFeeItems = JSON.parseArray(data, EcoCbfeeitem.class);
                cbFeeItemList.addAll(cbFeeItems);
            }
            if (CollUtil.isNotEmpty(cbFeeItemList)){
                gcl = cbFeeItemList.stream().filter(v -> v.getTargetamout() != null).map(EcoCbfeeitem::getTargetamout).reduce(BigDecimal.ZERO, BigDecimal::add);
            }
        }
        return gcl;
    }

    /**
     * 中位数
     * @param list
     * @return
     */
    public static BigDecimal getMedian(List<BigDecimal> list) {
        if (list == null || list.size() == 0) {
            return null;
        }
        List<BigDecimal> sortPrice = list.stream().sorted().collect(Collectors.toList());//对 价格 进行排序
        int i = sortPrice.size() / 2;
        return sortPrice.size()%2 == 0 ? (sortPrice.get(i - 1).add(sortPrice.get(i))).divide(new BigDecimal(2)).setScale(3,BigDecimal.ROUND_HALF_UP) : sortPrice.get(i).setScale(3,BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 去大去小平均值
     * @param list
     * @return
     */
    public static BigDecimal getQdqxAvg(List<BigDecimal> list) {
        if (list == null || list.size() == 0) {
            return null;
        }
        BigDecimal avgValue = null;
        List<BigDecimal> sortPrice = list.stream().sorted().collect(Collectors.toList());//对 价格 进行排序
        if (CollUtil.isNotEmpty(sortPrice)){
            double min = sortPrice.get(0).multiply(new BigDecimal(0.95)).doubleValue();//最小值去除5%
            double max = sortPrice.get(sortPrice.size() - 1).multiply(new BigDecimal(0.95)).doubleValue();//最大值去除5%
            sortPrice.set(0,new BigDecimal(min));
            sortPrice.set(sortPrice.size() - 1,new BigDecimal(max));
            avgValue = sortPrice.stream().reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(sortPrice.size()), 3, BigDecimal.ROUND_HALF_UP);
        }
        return avgValue;
    }
}
